package tg1;

 import java.io.*;
 import java.net.*;
 import java.sql.*;
 import java.util.Map;
 import java.util.HashMap;

 import java.nio.*;
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
 import java.util.*;

 import tg1.JdbcDAO;

public class TrackerHttpUtils {
	
 public static Map getRequestParameterMap(Socket s){
 	
	/*AVISO: STRINGBUILDER PODE USADO ABAIXO PARA FAZER UM TRATAMENTO 
	RAPIDO DA URL PRA PEGAR OS PARAMETROS DO REQUEST.
	A STRINGBUILDER *******NAO FAZ********  SICRONIA DE STRINGS ENTRE THREADS
	SE PRECISAR DISSO, DEIXE A STRINGBUFFER OU USE A CLASSE STRING NORMAL*/
			  			  
	  /**tomar cuidado aqui: peer_id NAO eh urlencoded, entao talvez de pau ao 
	desencodar ele*/
	try {		  
		  BufferedReader entrada = new BufferedReader(new InputStreamReader(s.getInputStream()));
		  String encodedURL= entrada.readLine();
		  Map map = new HashMap();
		  int isHttpConnection=encodedURL.indexOf("HTTP");
		  if (isHttpConnection == -1){
			  map.put("action", "trackerupdate");
			  map.put("modifiedPeers", encodedURL.getBytes("UTF-8"));
			  return map;
		  }
		
		 System.out.println("*************encodedURL="+encodedURL);
		System.out.println("*************indexOf /="+encodedURL.indexOf('/'));
		System.out.println("*************indexOf ?="+encodedURL.indexOf('?'));

		int indexLastSlash=encodedURL.indexOf('/');
		int indexLastInterrogation=encodedURL.indexOf('?');

		  String action = encodedURL.substring(indexLastSlash+1, indexLastInterrogation);
		
		  ////System.out.println("*************action="+action);
		  StringBuffer unencodedURL  = new StringBuffer (URLDecoder.decode(encodedURL , "UTF-8") );
		  ////System.out.println(unencodedURL.toString());
		  
		  
		unencodedURL.delete(0,unencodedURL.indexOf("?")+1);
		//ver se comecar a deletar pelo ultimo espaco elimina mesmo TODAS as coisas depois dos
		//parametros da url (no Ktorrent tah funcionando...)
		unencodedURL.delete(unencodedURL.lastIndexOf(" "), unencodedURL.length());
		String[] trackerParams =  unencodedURL.toString().split("&");
		
		
		
		map.put ("action", action);
		
		String[] paramPairAtual = null;
		int i=0;
		////System.out.println("numero de parametros da url"+trackerParams.length );
		if (action.equals("announce")){
			
			/* monte de sysouts pra debug*/
			for (i=0; i< trackerParams.length; i++){
				
				////System.out.println("parametro da url numero"+i +" ");
				////System.out.println(trackerParams[i]);
				
				if (trackerParams[i].indexOf("=")==-1){
					continue;
				}
				paramPairAtual= trackerParams[i].split("=");
				
				//System.out.print("key: ");
				//System.out.print(paramPairAtual[0]);
				//System.out.print(" value: ");
				//System.out.print(paramPairAtual[1]);
				
				map.put(paramPairAtual[0], paramPairAtual[1]) ;
				
				//System.out.print(" value no mapa:  ");
				
				////System.out.println(map.get(paramPairAtual[0]) + " ");
			}
		//	map.put("port", Integer.parseInt((String)map.get("port")));
		}
		
		else if(action.equals("scrape")){

			for (i=0; i< trackerParams.length; i++){
				//System.out.print("parametro da url numero"+i +" ");
				////System.out.println(trackerParams[i]);
				
				paramPairAtual= trackerParams[i].split("=");
				
				//System.out.print("key"+i+": ");
				//System.out.print(paramPairAtual[0]);
				//System.out.print(" value: ");
				//System.out.print(paramPairAtual[1]);
				
				map.put("info_hash"+i, paramPairAtual[1]) ;
				
				//System.out.print(" value no mapa:  ");
			}
			map.put("numHashes", new Integer(i));
		}	
		
		//if ( map.get("ip") == null){
			
			byte[] rawip = s.getInetAddress().getAddress();
		
			////System.out.println("********RawIp*************************"+rawip[0]+"."+rawip[1]+"."+rawip[2]+"."+rawip[3]);
			map.put ("ip", s.getInetAddress().getHostAddress());
			////System.out.println("********StringIp*************************"+(String)map.get("ip"));
			
			map.put("ipembytes", rawip);
			
			////System.out.println("*********************************porta"+s.getPort());
			
			map.put("port", new Integer(s.getPort()));
			//forcando a porta a ser inteiro
		//}	
		
		return map;
	}catch(Exception e){
		
		////System.out.println("Algum problema ocorreu no getRequestParameterMap. Imprimindo stacktrace.");
 	     		e.printStackTrace();
		return null;	
	}
 }
 
 /****************************************************************************/
 /****************************************************************************/	
public static void sendTrackerResponse(Socket s, byte[] bencodedResponse){
	
		try {  
			OutputStream os =  s.getOutputStream();
			os.write (("HTTP/1.1 ").getBytes("ASCII"));
			os.write ("200 ".getBytes("ASCII"));
			os.write ("OK \n\n".getBytes("ASCII"));
			
			//imprimindo response ateh peers
			os.write (bencodedResponse);
			
			os.write ("\n".getBytes("ASCII"));
			
		}catch(Exception e){
			          
			////System.out.println("Algum problema ocorreu no sendTrackerResponse. Imprimindo stacktrace.");
			e.printStackTrace();
		}	
	}
	
	/****************************************************************************/
	/****************************************************************************/	
			
	public static void sendErrorResponse(Socket s){
	
		try {  
			PrintStream ps = new PrintStream(s.getOutputStream());
			ps.print ("HTTP/1.1 ");
			ps.print ("200 ");
			ps.print ("OK \n\n");
			ps.println ("d14:failure_reason42:erro acessando o banco de dados do trackere");
			
		}catch(Exception e){
			//          
			////System.out.println("Algum problema ocorreu no sendTrackerResponse. Imprimindo stacktrace.");
			e.printStackTrace();
		}	
	}
	
	/****************************************************************************/
	/****************************************************************************/
	
	public static Selector getSelector(){
	
		try{
			/*Cria o ServerSocket na porta 2000, e fica no a//mandando uma response provisoria 
			trackerUtils.sendProvisoryTrackerResponse(s);ccept quando receber uma chamada, devolve um socket  pra tratar a conexao*/
			// Selector for incoming time requests
			Selector acceptSelector = SelectorProvider.provider().openSelector();
			
			// Create a new server socket and set to non blocking mode
			ServerSocketChannel ssc = ServerSocketChannel.open();
			ssc.configureBlocking(false);
			
			// Bind the server socket to the local host and port
			InetAddress lh = InetAddress.getLocalHost();
			////System.out.println ("usando endereco local"+lh.getHostAddress());
			InetSocketAddress isa = new InetSocketAddress(lh, 2000);
			//InetSocketAddress isa = new InetSocketAddress(lh, 32459);
			ssc.socket().bind(isa);
				
			// Register accepts on the server socket with the selector. This
			// step tells the selector that the socket wants to be put on the
			// ready list when accept operations occur, so allowing multiplexed
			// non-blocking I/O to take place.
			SelectionKey acceptKey = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
			
			return acceptSelector;
			
		}catch (Exception e2){
			////System.out.println ("Erro em getSelector:");
			e2.printStackTrace();
			return null;
		}	
		
	}
}
